這題要在一個數組中找一個峰值元素,並返回其索引位置,峰值元素定義為比左右相鄰元素大的元素,重點是,數組的左右邊界被視為負無窮大,所以邊界上的元素也可以當峰值。
理解題目:
題目要找到一個峰值元素,並要求算法的時間複雜度 O(log n),峰值定義是比相鄰元素大的元素,且可以返回任意一個峰值的索引(即使有多個峰值)數組的左邊界 nums[-1] 和右邊界 nums[n] 被視為負無窮大,這樣邊界元素也可能是峰值。
思路:
題目要求時間複雜度 O(log n),暗示應該用二分查找來解決這個問題,可以選擇把數組劃分成兩部分,通過比較當前中間元素跟相鄰元素來決定往哪邊繼續搜尋。
步驟:
初始化 left 和 right 指針,分別指向數組的開始和結束位置,用二分查找,比較中間元素 nums[mid] 跟右邊相鄰元素 nums[mid + 1],如果 nums[mid] > nums[mid + 1],說明峰值在左邊或當前位置,把 right 移到 mid,如果 nums[mid] < nums[mid + 1],表峰值在右邊,把 left 移到 mid + 1當 left == right 時,該位置就是峰值索引,返回該索引就完成了。
程式碼:
class Solution(object):
def findPeakElement(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
left, right = 0, len(nums) - 1
while left < right:
mid = (left + right) // 2
if nums[mid] > nums[mid + 1]:
right = mid # 峰值在左邊或當前中間位置
else:
left = mid + 1 # 峰值在右邊
return left # left 跟 right 相遇時即為峰值
思路:
用了二分查找的技巧,通過每次比較中間元素跟其相鄰的右邊元素來確定峰值的位置,當 nums[mid] > nums[mid + 1] 時,峰值ㄧ定在左側(包括當前中間位置),所以把 right 指針移到 mid;否則,峰值在右邊,所以移動left 指針,最後當 left == right ,就能確定峰值位置。
心得:
這題的重點在用二分法來優化,尤其是在對數據特性不明確的情況下用二分法,用二分法的關鍵是怎麼選擇劃分點並確定要搜索的範圍,這個思路讓我了解到解題時不僅要考慮數據本身的特性,還要善用時間複雜度優化的技巧。